package com.fc.push.handler.pub;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fc.commons.IDGenerator;
import com.fc.persistence.dao.DAOTemplate;
import com.fc.push.GlobalServerConst;
import com.fc.push.db.TranscationFacade;
import com.fc.push.db.entities.Application;
import com.fc.push.db.entities.IMessage;
import com.fc.push.exception.MServerException;
import com.fc.push.handler.AbstractTcpHandler;
import com.fc.push.handler.HandlerResult;
import com.fc.push.handler.pub.service.APNsPublishUtil;
import com.fc.push.handler.pub.service.GlobalService;
import com.fc.push.handler.pub.service.MqttPublishUtil;
import com.fc.push.handler.pub.service.RedisServiceUtil;
import com.fc.push.handler.pub.service.WebPublishService;
import com.fc.remoting.anno.Protocol;

import io.netty.channel.Channel;
import javapns.notification.PushNotificationPayload;

@Component
@Protocol(module = PublishConst.PUBLISH_MODULE_ID,order = PublishConst.ORDER_4)
public class PublishMsgRpcHandler extends AbstractTcpHandler{
	private static final String APPKEY = "appkey";
	private static final String PLATFORM = "platform";
	private static final String MESSAGE = "message";
	private static final String AUDIENCE = "audience";
	private static final String REGISTRATION_ID = "registration_id";
	
	private static final String CODE = "code";
	
	@Autowired
	APNsPublishUtil apnsPublishUti;
	@Autowired
	MqttPublishUtil mqttPublishUtil;
	@Autowired 
	RedisServiceUtil redisServiceUtil;
	
	@Autowired 
	GlobalService globalService;
	
	@Override
	protected Object handle(Channel channel, JSONObject request) {
		String platform = request.getString(PLATFORM);
		JSONObject audience = request.getJSONObject(AUDIENCE);
		JSONObject message = request.getJSONObject(MESSAGE);
		String appkey = request.getString(APPKEY);
		if (platform == null || platform.isEmpty()) {
			JSONObject object = HandlerResult.result();
			object.put(CODE, MessageRCode.RCODE_ERROR_1002);
			return object;
		}
		platform = platform.toLowerCase();

		String sql_app = "from " + Application.class.getSimpleName() + " where appkey = '" + appkey + "'";
		List<DAOTemplate> applist = TranscationFacade.getInstance().transcation().getBySQL(sql_app);
		if (applist == null || applist.size() == 0) {
			JSONObject object = HandlerResult.result();
			object.put(CODE, MessageRCode.RCODE_ERROR_1008);
			return object;
		}

		Application application = (Application) applist.get(0);
		if (!application.getPlatform().equals(platform)) {
			JSONObject object = HandlerResult.result();
			object.put(CODE, MessageRCode.RCODE_ERROR_1004);
			return object;
		}
		platform = application.getPlatform();
		// 保存发送的消息
		IMessage iMessage = new IMessage();
		iMessage.setId(IDGenerator.INSTANCE.generateId());
		iMessage.setMsg(message.toJSONString());
		iMessage.setAppkey(application.getAppkey());
		iMessage.setCreatedate(new Date());
		
		// 保存消息的条数
		String countkey = GlobalServerConst.APP_MESSAGE_COUNT.replaceFirst("APP", appkey);
		if (redisServiceUtil.existsProxy(countkey)) {
			redisServiceUtil.incrProxy(countkey);
		} else {
			redisServiceUtil.incrProxy(countkey);
			redisServiceUtil.incrProxy(countkey);
		}
		
		// 开始发送消息的逻辑
		if (audience != null) {
			JSONArray id = null;
			if ((id = audience.getJSONArray(REGISTRATION_ID)) != null) {
				/**
				 * 通过id来推送
				 */
				Object[] ids = id.toArray();
				if (ids.length > 0) {
					if (platform.toLowerCase().equals(GlobalServerConst.ANDROID)) {
						MqttMessage payload = null;
						try {
							payload = mqttPublishUtil.assMqttPayload(message);
						} catch (UnsupportedEncodingException e) {
							globalService.setRCodeAndSave(iMessage, MessageRCode.RCODE_ERROR_1000);
							throw new MServerException(e, e.getMessage());
						}

						// 过滤掉未注册的设备
						List<Object> idList = new ArrayList<Object>();
						Collections.addAll(idList, ids);
						globalService.filterUnregisteredIDWhenPushedByID(idList, appkey);
						// 推送
						mqttPublishUtil.pubMessageBySlice(appkey, payload, idList.toArray());
					} else if (platform.toLowerCase().equals(GlobalServerConst.IOS)) {
						// 根据TOKEN数组推送IOS消息
						
						// 过滤掉未注册的设备
						List<Object> idList = new ArrayList<Object>();
						Collections.addAll(idList, ids);
						List<Object> result = globalService.filterUnregisteredIDWhenPushedByID(idList, appkey);
						
						//Mqtt推送
						MqttMessage mqttPayload = null;
						try {
							mqttPayload = mqttPublishUtil.assMqttPayload(message);
						} catch (UnsupportedEncodingException e) {
							globalService.setRCodeAndSave(iMessage, MessageRCode.RCODE_ERROR_1000);
							throw new MServerException(e, e.getMessage());
						}
						mqttPublishUtil.pubMessageBySlice(appkey, mqttPayload, result.toArray());
						
						// APNs推送
						PushNotificationPayload apnsPayload = null;
						try {
							apnsPayload =apnsPublishUti.assIOSPayload(message);
						} catch (org.json.JSONException e) {
							globalService.setRCodeAndSave(iMessage, MessageRCode.RCODE_ERROR_1000);
							throw new MServerException(e, e.getMessage());
						}
						// 是否是生产环境
						boolean isProduction = false;
						if (application.getIsproduction() == 1) {
							isProduction = true;
						}
						
						apnsPublishUti.pubMessageBySlice(application.getFile(), application.getPwd(),
								apnsPayload, isProduction, idList.toArray());
					} else if (platform.toLowerCase().equals(GlobalServerConst.WEB)) {
						List<Object> idList = new ArrayList<Object>();
						Collections.addAll(idList, ids);
						// 过滤掉未注册的设备
						globalService.filterUnregisteredIDWhenPushedByID(idList, appkey);
						// 推送
						WebPublishService.getInstance().pubMessageBySlice(idList.toArray(), message);
					}
				}
			}		
		}
		globalService.setRCodeAndSave(iMessage, MessageRCode.RCODE_SUCCESS);
		return HandlerResult.result();
	}
}
